require "Common/define"
require "Logic/Config"
require "Common/functions"
require "Common/Class"
require "Net/weaponHandler"
-- 奇异碎片 管理类
-- ZhengFeng 2021.03.11
------------------------------------------------------------------
StrangeFragmentManager = {}
local this = StrangeFragmentManager
this.FragmentInfoList = {}

this.const_panel = {list = 1, levelUp = 2, baptism = 3}
this.panel_info  = nil
this.partnerId = nil
this.isChange = nil
--获取配置表信息
function this.Init()
    
end

function this.GetAllDebris()
    -- local ls = {}
    -- for k,v in pairs(this.FragmentInfoList) do
    --     table.insert(ls, v)
    -- end
    -- table.sort(ls, this.fragmentSort)
    return this.FragmentInfoList
end

function this.GetAllDebrisCount( _quality ) 
    local count = 0
    for _,v in pairs(this.FragmentInfoList) do
        if _quality == nil then
            count = count + 1
        elseif _quality == v.quality then
             count = count + 1
        end
    end 
    return count
end

--通过碎片id获取配置表信息
function this.GetTableByFragmentId(fragmentId)
    return G.dataTable["t_debris"][tostring(fragmentId)]
end

function this.GetDebrisByItemid(id)
    return this.FragmentInfoList[tostring(id)]
end

--通过英雄id获取奇异碎片信息
function this.GetFragmentInfoByPartnerId(partnerId)
    return this.GetCurrentEquipFragment(partnerId)
end

--获取当前英雄装备的碎片
function this.GetCurrentEquipFragment(partnerId)
    partnerId = tostring(partnerId)
    for _, value in pairs(this.FragmentInfoList) do
        if value.partnerId and value.partnerId == partnerId then
            return value
        end
    end
    return nil
end
--获取空闲的碎片
function this.GetOwnFragmentList(chip)
    local _fragmentList = {}
    for _, value in pairs(this.FragmentInfoList) do
        if chip then
            if value.itemId ~= chip.itemId and string.IsNilOrEmpty(value.partnerId)  then  --and value.lock == 0
                table.insert(_fragmentList,value)
            end
        else
            if string.IsNilOrEmpty(value.partnerId)  then  --and value.lock == 0
                table.insert(_fragmentList,value)
            end
        end
    end
    return _fragmentList
end
--排序
function this.UpdateFragmentList()
    -- table.sort(this.FragmentInfoList, this.fragmentSort)
    -- FireEvent(Config.EventType.Fragment_Add)
end

--获取专武-碎片列表
function this.GetWeaponFragmentList(currentPartnerId)
    local _tempList = {}
    for key, value in pairs(this.FragmentInfoList) do
        if value.partnerId then
            local _heroData = HeroManager.getHeroDatabyPartnerId(value.partnerId,true)
            value.heroName = _heroData.name
            value.heroIcon = "ui://ICONAtlas/".._heroData.icon
        end
        table.insert(_tempList,value)
    end
    
    return _tempList
end

function this.fragmentSort(a,b)       --> 奇异碎片：品质（从高到低）
    if not string.IsNilOrEmpty(a.partnerId) then
        if not string.IsNilOrEmpty(b.partnerId) then
            -- a b 都已镶嵌在玩家身上
            if a.quality > b.quality then
                return true
            end
            return false
        end
        -- a碎片已镶嵌，b碎片未镶嵌
        return true
    elseif not string.IsNilOrEmpty(b.partnerId) then
        -- b碎片已镶嵌，a碎片未镶嵌
        return false
    end
    if not string.IsNilOrEmpty(a.itemId) then
        if not string.IsNilOrEmpty(b.itemId) then
            --a b 都已经获得
            if a.quality > b.quality then
                return true
            end
            return false
        end
        --只获得碎片a，未获得碎片b
        return true
    elseif not string.IsNilOrEmpty(b.itemId) then
        --只获得碎片b，未获得碎片a
        return false
    end

    if a.quality > b.quality then
        return true
    end
    return false
end

local sort_chip = function(a, b)
    if a.quality ~= b.quality then
        return a.quality > b.quality
    else
        if a.level ~= b.level then
            return  a.level > b.level
        end
    end
    return a.itemId > b.itemId
end

------------------------------------------------------------------
--服务器协议
--新增碎片
function this.ResAddFragment(item,sourceCode,params)
    local _newFragment = nil
    local _newIndex = -1
    local _lastCount = 0
   
    if this.m_t_debris == nil then
        this.m_t_debris = G.dataTable["t_debris"]
    end

    if this.m_t_debris[tostring(item.itemModelId)] == nil then
        return
    end
    local item_id = tostring(item.itemId)

    if this.FragmentInfoList[item_id] then
        local chip = this.FragmentInfoList[item_id]

        local oid = chip.partnerId --刷新前记录下来
        if item.parameters then
            local js = decodeJsonStrToTabel(item.parameters)
            if js then
                chip.exp = js.DEBRIS_EXP and tonumber(js.DEBRIS_EXP) or 0
                chip.level = js.DEBRIS_LV and tonumber(js.DEBRIS_LV) or 1
                chip.tempSkills = js.DEBRIS_TEMP_SKILL and this.parseSubSkills(js.DEBRIS_TEMP_SKILL) or chip.tempSkills
                chip.subSkills = js.DEBRIS_SUB_SKILL and this.parseSubSkills(js.DEBRIS_SUB_SKILL) or chip.subSkills

                chip.skillList  = {{mianSkill = chip.f_SkillId}}
                chip.addPower = dataTable.getDataTableByStringId("t_debrismajorskill",chip.f_SkillId + chip.level,"f_DebrisLevelPower")
            end
        end
        chip.partnerId = item.partnerId and tostring(item.partnerId)
        this.RefreshHeroAttr(oid, chip)
    else--DEBRIS_LOCK
        
        -- if item.partnerId then
        --     weaponHandler.ReqDebrisDetail(item.partnerId, tostring(item.itemId))
        -- else
        --     weaponHandler.ReqDebrisDetail(0, tostring(item.itemId))
        -- end
        
        local chip = this.FormationChip(item)
        if chip then
            this.FragmentInfoList[item_id] = chip

            if chip.partnerId then
                this.RefreshHeroAttr(chip.partnerId, chip)
            end
        end
    end
    local mid = tostring(item.itemModelId)
    
    TAManager.TrackItemEvent(item["itemId"],item["itemModelId"],item["num"],_lastCount,sourceCode,params)
end

--创建新的碎片
function this.FormationChip(item)
    local chip = this.m_t_debris[tostring(item.itemModelId)]
    if not chip then
        return nil
    end
    local modelId = item.itemModelId
    local _fragmentItem = nil

    local _itemInfo = nil
    if chip.f_Show == 1 then
        _fragmentItem = {}
        _fragmentItem.itemModelId   = tostring(modelId)
        _itemInfo = G.dataTable["t_item"][tostring(modelId)]
        _fragmentItem.debrisType    = chip.f_DebrisType
        if _itemInfo then
            _fragmentItem.colorname = getLanguage(_itemInfo.f_ItemName)
            _fragmentItem.name      = getLanguage(_itemInfo.f_ItemName)--string.gsub(_fragmentItem.colorname, "%b[]", "")
            _fragmentItem.icon      = _itemInfo.f_Icon
            _fragmentItem.quality   = _itemInfo.f_Quality
            _fragmentItem.desc      = getLanguage(_itemInfo.f_Desc)
            _fragmentItem.f_Add     = chip.f_Add
        end
        _fragmentItem.tabType       = EnumConst.ItemTableEnum.Fragment
        _fragmentItem.itemType      = EnumConst.ItemTypeEnum.Fragment
        _fragmentItem.part          = EnumConst.EquipPartEnum.FRAGMENT
        _fragmentItem.itemId        = tostring(item.itemId)--tostring(item.itemId)
        -- _fragmentItem.num           = item.num
        _fragmentItem.partnerId     = item.partnerId
        _fragmentItem.f_DropDes     = getLanguage(chip.f_DropDes)
        _fragmentItem.f_SkillId     = chip.f_SkillId
        _fragmentItem.level         = item.level and item.level or 1
        _fragmentItem.lock          = item.lock and item.lock or 0
        _fragmentItem.exp           = item.exp and item.exp or 1
        _fragmentItem.carrayCount   = chip.f_Carryableskills --携带子技能最大数量

        _fragmentItem.subSkills     = item.subSkills or {}
        _fragmentItem.skillList     = {{mianSkill = chip.f_SkillId}}
        local js = decodeJsonStrToTabel(item.parameters)
        if js then
            _fragmentItem.exp = js.DEBRIS_EXP and tonumber(js.DEBRIS_EXP) or 0
            _fragmentItem.level = js.DEBRIS_LV and tonumber(js.DEBRIS_LV) or 1
            _fragmentItem.lock = js.DEBRIS_LOCK and tonumber(js.DEBRIS_LOCK) or 0
            _fragmentItem.tempSkills = js.DEBRIS_TEMP_SKILL and this.parseSubSkills(js.DEBRIS_TEMP_SKILL) or chip.tempSkills
            _fragmentItem.subSkills = js.DEBRIS_SUB_SKILL and this.parseSubSkills(js.DEBRIS_SUB_SKILL) or chip.subSkills

            _fragmentItem.skillList  = {{mianSkill = chip.f_SkillId}}
        end

        _fragmentItem.GetAttr = function()
            if not _fragmentItem.level then
                _fragmentItem.level = 1
            end
            local key = _fragmentItem.f_SkillId + _fragmentItem.level
            local cg = dataTable.getDataTableByStringId("t_debrismajorskill",key)
            if cg then
                return decodeJsonStrToTabel(cg.f_DebrisBasic)
            else
                return {}
            end
        end
        _fragmentItem.GetMainSkillDes = function()
            if not _fragmentItem.level then
                _fragmentItem.level = 1
            end
            local key = _fragmentItem.f_SkillId + _fragmentItem.level
            local cg = dataTable.getDataTableByStringId("t_debrismajorskill",key)
            if cg then
                return getLanguage(cg.f_DebrisLevelDesc)
            else
                return getLanguage("DebrisLevelDesc" .. key)
            end
        end
        _fragmentItem.addPower = dataTable.getDataTableByStringId("t_debrismajorskill",_fragmentItem.f_SkillId + _fragmentItem.level,"f_DebrisLevelPower")
        _fragmentItem.GetSubSkillDes = function(skillid)
            local config = G.dataTable["t_skill"][tostring(skillid)]
            
            local des = getLanguage("SkillDesc103100" .. skillid)
            if config then 
                des = getLanguage(config.f_Desc)
            end
            
            return des
        end
    end
    return _fragmentItem
end

function this.RefreshHeroAttr(pid, chip)
    local key = chip.f_SkillId + chip.level
    local cg = dataTable.getDataTableByStringId("t_debrismajorskill",key)
    if cg then
        local tb = cg.f_DebrisBasic
        local hero
        if chip.partnerId then
            local attr = {}
            hero = HeroManager.getHeroDatabyPartnerId(chip.partnerId, true)
            for k,v in pairs(tb) do
                attr[v[1]] = v[2]
            end
        
            hero.allAttribute[EnumConst.AttributeTypeEnum.Debris] = attr
        else
            hero = HeroManager.getHeroDatabyPartnerId(pid, true)
            if hero then
                hero.allAttribute[EnumConst.AttributeTypeEnum.Debris] = nil
            end
        end
        --logError("计算魂石属性")
       --[[ if hero then
            HeroManager.processHeroAllAttr(hero)
        end--]]
    end
end

--根据唯一id获取碎片
function this.GetFragmentByItemId(itemid)
    if this.FragmentInfoList[itemid] then
        return this.FragmentInfoList[itemid]
    end
    log(">>>>>>>>>>>>>>>>奇异碎片为空 itemid = " .. itemid)
    return nil
end

--镶嵌碎片
function this.ResFragmentInlay(message)
    local f = this.GetFragmentByItemId(tostring(message.itemId))
    if f then
        f.partnerId = tostring(message.partnerId)
        this.RefreshHeroAttr(tostring(message.partnerId), f)
    end
    logicMgr.HeroManager.updateHeroBaseAttr(tostring(message.partnerId),true);
    FireEvent(Config.EventType.Fragment_Wear, message)
    FireEvent(Config.EventType.Fresh_Fragment)
end

--设置洗练状态
function this.SetBaptismStatus(status)
    this.baptismStatus = status
end

function this.GetBaptismStatus()
    return this.baptismStatus or Config.Baptism_Step.None
end

function this.RefreshState(baptism)
    this.baptism = baptism
end

function this.ClearPanelInfo()
    this.panel_info = {}
end

function this.GetPanelInfo()
    return this.panel_info
end

--卸下碎片
function this.ResFragmentDemount(message)
    local f = this.GetFragmentByItemId(tostring(message.itemId))
    if f then
        local hero = HeroManager.getHeroDatabyPartnerId(f.partnerId, true)
        if hero then
            hero.allAttribute[EnumConst.AttributeTypeEnum.Debris] = nil
        end
        logicMgr.HeroManager.updateHeroBaseAttr(tostring(message.partnerId),true);
        f.partnerId = nil
        -- this.RefreshHeroAttr(tostring(message.partnerId), f)
    end
    FireEvent(Config.EventType.Fragment_Unwear)
    FireEvent(Config.EventType.Fresh_Fragment)
end
--替换碎片
function this.ResFragmentReplace(message)
    --主动替换碎片的英雄
    local _partnerId = tostring(message.partnerId)
    --被动替换碎片的英雄
    local _otherId = tostring(message.partnerId2)

    for index, value in pairs(this.FragmentInfoList) do
        if value.partnerId then
            if  value.partnerId == _partnerId then
                this.FragmentInfoList[index].partnerId = tostring(_otherId)
                this.RefreshHeroAttr(this.FragmentInfoList[index].partnerId, this.FragmentInfoList[index])
            elseif value.partnerId == _otherId then
                this.FragmentInfoList[index].partnerId = tostring(_partnerId)
                this.RefreshHeroAttr(this.FragmentInfoList[index].partnerId, this.FragmentInfoList[index])
            end
        end
    end
    logicMgr.HeroManager.updateHeroBaseAttr(tostring(message.partnerId),true);
    FireEvent(Config.EventType.Fragment_Replace)
    FireEvent(Config.EventType.Fresh_Fragment)
end

--碎片升级一键狗粮
function this.QuickChooseGradeFood()
    for k,v in pairs(this.FragmentInfoList) do
        
    end
end

--品质筛选
function this.FilterQuality( quality)
    if quality == nil then
        return {}
    end
    local ls = {}
    for k,v in pairs(this.FragmentInfoList) do
        if v.quality == quality then
            table.insert(ls, v)
        end
    end
    -- table.sort(ls, this.fragmentSort)
    return ls
end

--职业筛选
function this.FilterProfession(job, quality)
    local ls = {}
    for k,v in pairs(this.FragmentInfoList) do 
        if job == 0 then
            table.insert(ls, v)
        else
            if quality then
                if v.quality == quality and v.debrisType == job then
                    table.insert(ls, v)
                end
            else
                if v.debrisType == job then
                    table.insert(ls, v)
                end
            end
        end
    end
    return ls
end

--查询详情
function this.UpdateDetail(detail)
    local chip = this.GetDebrisByItemid(detail.itemId)
    if chip then
        chip.detail     = true
        chip.level      = detail.lv
        chip.lock       = detail.lock
        chip.subSkills  = detail.subSkills
        chip.tempSkills = detail.tempSubSkills
        chip.exp        = tonumber(tostring(detail.exp))
        chip.skillList  = {{mianSkill = chip.f_SkillId}}
        chip.addPower   = dataTable.getDataTableByStringId("t_debrismajorskill",chip.f_SkillId + chip.level,"f_DebrisLevelPower")
        
        -- if detail.subSkills then
        --     for k,v in pairs(detail.subSkills) do
        --         table.insert(chip.skillList, v)
        --     end
        -- end

        -- 魂石突破
        if tostring(chip.itemModelId) ~= tostring(detail.modelId) then
            chip.itemModelId = tostring(detail.modelId)
            this.FragmentInfoList[tostring(detail.itemId)] = this.FormationChip(chip)
            chip = this.FragmentInfoList[tostring(detail.itemId)]
        end
        
        -- 更新英雄数据
        if chip.partnerId then
            this.RefreshHeroAttr(tostring(chip.partnerId), chip)
            logicMgr.HeroManager.updateHeroBaseAttr(tostring(chip.partnerId), true)
        end

        FireEvent(Config.EventType.DebrisUpdate)
        FireEvent(Config.EventType.Fresh_Fragment)
    end
end

function this.GetBaptismList(chip)
    local list = {}
    if chip then
        for k,v in pairs(this.FragmentInfoList) do
            if v.itemModelId == chip.itemModelId and v.partnerId == nil then
                table.insert(list, v)
            end
        end
    else
        for k,v in pairs(this.FragmentInfoList) do
            if  v.quality >= 6 then -- v.partnerId and
                table.insert(list, v)
            end
        end
    end
    return list
end

--设置通用item
function this.SetItemData(obj, data, showHero)
    local item = CtrlManager.GetCtrl(PanelNames.Item);
    if item then
        local ctr_debris = obj:GetController("debris")
        local it_debris = obj:GetChild("debris")
        local txt_level = it_debris:GetChild("level")
        local ctr_lock = it_debris:GetController("lock")
        local img_type = it_debris:GetChild("Occupation")

        ctr_debris.selectedIndex = 1
        it_debris:GetController("owner").selectedIndex = data.partnerId and 1 or 0
        
        if ctr_lock then
            ctr_lock.selectedIndex = data.lock == 1 and 1 or 0
        end

        if txt_level then
            txt_level.text =  data.level
        end

        item.initData(obj, data, 1, true, nil,  data.partnerId)

        local _heroData = HeroManager.getHeroDatabyPartnerId(data.partnerId,true)
        if showHero and _heroData  then
            local url = "ui://ICONAtlas/".._heroData.icon
            it_debris:GetChild("hero"):GetChild("HeadIcon").url = url
        else
            it_debris:GetController("owner").selectedIndex = 0
            it_debris:GetChild("hero"):GetChild("HeadIcon").url = ""
        end

        it_debris:GetChild("Occupation").url = EnumConst.Path_DebrisTypeIcon["type_" .. data.debrisType]

        local txt_Level = obj:GetChild("level")
        txt_Level.text = ""
    end
end

--删除
function this.RemoveDebris(itemid)
    local tb = nil
    if type(itemid) == "table" then
        for k,v in pairs(itemid) do
            this.FragmentInfoList[tostring(v)] = nil
        end
    elseif type(itemid) == "string" then
        this.FragmentInfoList[itemid] = nil
    end
    -- TAManager.TrackItemEvent(itemid, item["itemModelId"], 0, item["num"], sourceCode, params)
    FireEvent(Config.EventType.DebrisUpdate)
    
end

function this.Track_DebrisLevelup(chip, last_exp, last_level)
    if not chip then
        return
    end
    local dic           = {}
    dic.item_id         = chip.itemId
    dic.item_model_id   = chip.itemModelId
    dic.main_skill      = tostring(chip.f_SkillId + chip.level)
    dic.last_exp        = last_exp
    dic.cur_exp         = chip.exp
    dic.last_level      = last_level
    dic.cur_level       = chip.level

    TAManager.TrackByDictionary("debris_level", dic)
end

function this.GetMainDesc(modelid, level)
    local chip = G.dataTable["t_debris"][tostring(modelid)]
    if chip then
        local key = chip.f_SkillId + level
        local cg = dataTable.getDataTableByStringId("t_debrismajorskill",key)
        if cg then
            return getLanguage(cg.f_DebrisLevelDesc)
        end
    end
    return ""
end

function this.GetChipAttr(modelid, level)
    local chip = G.dataTable["t_debris"][tostring(modelid)]
    if chip then
        local key = chip.f_SkillId + level
        local cg = dataTable.getDataTableByStringId("t_debrismajorskill",key)
        if cg then
            return decodeJsonStrToTabel(cg.f_DebrisBasic)
        end
    end
    return ""
end

--是否可以替换
function this.CheckTheChipChangeCondition(chip)
    if chip == nil then
        local list = StrangeFragmentManager.GetOwnFragmentList()
        if next(list) ~= nil then
            return true
        else
            return false
        end
    elseif chip.itemId == nil then
        return false
    end
   
    local list = StrangeFragmentManager.GetOwnFragmentList(chip)
    for k,v in pairs(list) do
        if v.quality > chip.quality and v.name == chip.name then
            return true
        end
    end
    return false
end

--是否满足升级条件
function this.CheckTheChipUpgrade(chip)
    if chip == nil or chip.itemId == nil then
        return false
    end
    local key = tonumber(chip.f_SkillId) + chip.level
    local cur_skill = dataTable.getDataTableByStringId("t_debrismajorskill",key)
    local next_skill = dataTable.getDataTableByStringId("t_debrismajorskill",key + 1)

    local b = false

    local need = 0
    if next_skill then
        need = next_skill.f_TotalExp
    end

    if need == 0 then
        return false
    end

    local select_exp = chip.exp

    local list = StrangeFragmentManager.GetOwnFragmentList(chip)

    local it1 = ItemManager.getItemIdByModelId(200026)
    local it2 = ItemManager.getItemIdByModelId(200027)

    if it1 then
        local item = logicMgr.ItemManager.getItemData(it1)
        select_exp = select_exp + item.num * item.itemFunction[2]
    end
    if it2 then
        local item = logicMgr.ItemManager.getItemData(it2)
        select_exp = select_exp + item.num * item.itemFunction[2]
    end
    if select_exp >= need then
        return true
    end

    local sk_config
    for k,v in pairs(list) do
        if v.quality <= chip.quality then
            sk_config = dataTable.getDataTableByStringId("t_debrismajorskill",v.f_SkillId + v.level)
            if sk_config then
                select_exp = select_exp + sk_config.f_Exp
            else
                select_exp = select_exp + 0
            end
        end
        if select_exp >= need then
            b = true
            break
        end
    end
    return b
end

-- 是否可以突破
function this.CheckTheChipBroken(chip)
    if chip == nil or chip.itemId == nil then
        return false
    end

    if chip.quality ~= EnumConst.DebrisQuality.Immortal then
        return false
    end

    local costData = decodeJsonStrToTabel(dataTable.getGlobalString(631))
    if not costData then
        return false
    end

    local currNum = logicMgr.ItemManager.getItemCountbyModelId(costData[1])
    return currNum >= costData[2]
end

function this.clearData()
    this.FragmentInfoList = {}
end

--- 解析技能数据
--- @private
function this.parseSubSkills(skillData)
    local tb  = decodeJsonStrToTabel(skillData)
    if tb == nil or tb.map == nil then
        printError("魂石子技能数据有误")
        return nil
    end

    local ret = {}
    for k, v in pairs(tb.map) do
        table.insert(ret, v)
    end
    table.sort(ret, function(v1, v2) return v1.index < v2.index end)
    
    return ret
end

return this

